package com.tools.scanner.utils

import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.media.ExifInterface
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.io.OutputStream

class ImageUtil {
    companion object {

        fun saveToFile(context: Context, bitmap: Bitmap): File? {
            val file = File(context.cacheDir, "${System.currentTimeMillis()}.png")
            try {
                FileOutputStream(file).use { out ->
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)
                }
                return file
            } catch (e: Exception) {
                e.printStackTrace()
                return null
            }
        }

        fun readImageFile(imagePath: String): Bitmap {
            val options = BitmapFactory.Options()
            options.inPreferredConfig = Bitmap.Config.ARGB_8888
            val bitmap = BitmapFactory.decodeFile(imagePath, options)
            return rotateBitmap(imagePath, bitmap)
        }

        fun rotateBitmap(imagePath: String, bitmap: Bitmap): Bitmap {
            val exif = ExifInterface(imagePath)
            val orientation = exif.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_UNDEFINED
            )

            val rotationDegrees = when (orientation) {
                ExifInterface.ORIENTATION_ROTATE_90 -> 90
                ExifInterface.ORIENTATION_ROTATE_180 -> 180
                ExifInterface.ORIENTATION_ROTATE_270 -> 270
                else -> 0
            }

            return if (rotationDegrees != 0) {
                val matrix = android.graphics.Matrix()
                matrix.postRotate(rotationDegrees.toFloat())
                Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
            } else {
                bitmap
            }
        }

        fun uriToBitmap(context: Context, uri: Uri): Bitmap? {
            return try {
                val contentResolver = context.contentResolver
                val inputStream: InputStream? = contentResolver.openInputStream(uri)
                BitmapFactory.decodeStream(inputStream).also {
                    inputStream?.close()
                }
            } catch (e: Exception) {
                e.printStackTrace()
                null
            }
        }

        fun saveToGallery(context: Context, uri: Uri): Boolean {
            return saveToGallery(context) { contentResolver, output ->
                contentResolver.openInputStream(uri)?.use { input ->
                    input.copyTo(output)
                }
            } != null
        }

        fun saveToGallery(context: Context, bitmap: Bitmap): Boolean {
            return saveToGallery(context) { contentResolver, output ->
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output)
            } != null
        }

        fun saveToGallery(context: Context, uriList: List<Uri>) {
            val savedUris = mutableListOf<Uri>()

            for (uri in uriList) {
                if (saveToGallery(context, uri)) {
                    savedUris.add(uri)
                }
            }

            if (savedUris.isNotEmpty()) {
                scanFiles(context, savedUris)
            }
        }

        private fun saveToGallery(
            context: Context,
            callback: (contentResolver: ContentResolver, output: OutputStream) -> Unit
        ): Uri? {
            val contentResolver = context.contentResolver

            try {
                val contentValues = ContentValues().apply {
                    put(
                        MediaStore.Images.Media.DISPLAY_NAME,
                        "scan_${System.currentTimeMillis()}.jpg"
                    )
                    put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                        put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
                        put(MediaStore.Images.Media.IS_PENDING, 1)
                    }
                }

                val targetUri = contentResolver.insert(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    contentValues
                ) ?: return null

                contentResolver.openOutputStream(targetUri)?.use { output ->
                    callback(contentResolver, output)
                }

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    contentValues.clear()
                    contentValues.put(MediaStore.Images.Media.IS_PENDING, 0)
                    contentResolver.update(targetUri, contentValues, null, null)
                }

                return targetUri
            } catch (e: Exception) {
                e.printStackTrace()
                return null
            }
        }

        private fun scanFiles(context: Context, uris: List<Uri>) {
            val paths = uris.map { it.path }.toTypedArray()
            MediaScannerConnection.scanFile(
                context,
                paths,
                arrayOf("image/jpeg")
            ) { _, _ -> }
        }
    }
}
